package cn.virens.common.spring.retry.annotations.config;

import cn.virens.common.spring.annotations.config.VirAbstractImportAware;
import cn.virens.common.spring.retry.annotations.handler.VirRetryAnnotationSource;
import cn.virens.common.spring.retry.annotations.handler.VirRetryMethodInterceptor;
import cn.virens.common.spring.retry.annotations.handler.VirRetryMethodPointcutAdvisor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.core.Ordered;

import java.lang.annotation.Annotation;

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class VirRetryConfiguration extends VirAbstractImportAware {

    @Bean("virRetryAnnotationSource")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirRetryAnnotationSource virRetryAnnotationSource() throws Exception {
        return new VirRetryAnnotationSource();
    }

    @Bean("virRetryMethodInterceptor")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirRetryMethodInterceptor virRetryMethodInterceptor(//
                                                               @Qualifier("virRetryAnnotationSource") VirRetryAnnotationSource virRetryAnnotationSource//
    ) throws Exception {
        return new VirRetryMethodInterceptor(virRetryAnnotationSource);
    }

    @Bean("virRetryMethodPointcutAdvisor")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirRetryMethodPointcutAdvisor virRetryMethodPointcutAdvisor(@Qualifier("virRetryAnnotationSource") VirRetryAnnotationSource virRetryAnnotationSource,//
                                                                       @Qualifier("virRetryMethodInterceptor") VirRetryMethodInterceptor virRetryMethodInterceptor//
    ) throws Exception {
        VirRetryMethodPointcutAdvisor advisor = new VirRetryMethodPointcutAdvisor();
        advisor.setOrder(getInteger("order", Ordered.LOWEST_PRECEDENCE));
        advisor.setAnnotationSource(virRetryAnnotationSource);
        advisor.setAdvice(virRetryMethodInterceptor);

        return advisor;
    }

    @Override
    protected Class<? extends Annotation> getAnnotationClass() {
        return EnableVirRetry.class;
    }
}
